package com.googlecode.sparda.commons.util;

import java.text.DecimalFormat;

/**
 * This class is a highly customizable {@link PercentageFormat} for a {@link Percentager}.
 * The class provide to build a tiny human readable string format for a percentage.
 * @author Fabio Grucci (<i>alias</i> <b>Phoenix</b>)
 * @see Percentager
 */
public class CustomizablePercentageFormat implements PercentageFormat {
	/**
	 * The decimal format for the percentage.
	 */
	private final DecimalFormat percentageFormat;
	/**
	 * The decimal format for the partial count. 
	 */
	private final DecimalFormat partialCountFormat;
	/**
	 * A string at the beginning of string format.
	 */
	private final String beginString;
	/**
	 * A string at the end of string format.
	 */
	private final String endString;
	/**
	 * A string between percentage and and partial.
	 */
	private final String compositionString;
	/**
	 * Boolean <code>false</code> if the total step count must be hidden.
	 */
	private boolean showTotal;
	/**
	 * Boolean <code>false</code> if the partial step count must be hidden.
	 */
	private boolean showPartial;
	/**
	 * Boolean <code>false</code> if the total percentage must be hidden.
	 */
	private boolean showPercentage;
	/**
	 * Boolean <code>false</code> if the percentage must be at the end of the string.
	 */
	private boolean firstPercentage;
	
	public CustomizablePercentageFormat(DecimalFormat percentageFormat, DecimalFormat partialCountFormat) {
		this(percentageFormat, partialCountFormat, "", " (", ")"); 
	}
	
	public CustomizablePercentageFormat(DecimalFormat percentageFormat, DecimalFormat partialCountFormat, String compositionString) {
		this(percentageFormat, partialCountFormat, "", compositionString, "");
	}
	
	public CustomizablePercentageFormat(DecimalFormat percentageFormat, DecimalFormat partialCountFormat, String beginString, String compositionString, String endString) {
		this.percentageFormat = percentageFormat;
		this.partialCountFormat = partialCountFormat;
		this.beginString = beginString;
		this.compositionString = compositionString;
		this.endString = endString;
		this.showTotal = true;
		this.showPartial = true;
		this.showPercentage = true;
		this.firstPercentage = true;
	}
	
	/* (non-Javadoc)
     * @see com.googlecode.sparda.commons.util.PercentageFormat#format(double, int, int)
     */
	@Override
	public String format(double percentage, int currenStep, int totalStepCount) {
		StringBuilder result = new StringBuilder();
		result.append(this.beginString);
		String toAppend;
		if(this.firstPercentage)
			toAppend = this.formatPercentage(percentage);
		else
			toAppend = this.formatPartialTotal(currenStep, totalStepCount);
		result.append(toAppend);
		result.append(this.compositionString);
		if(!this.firstPercentage)
			toAppend = this.formatPercentage(percentage);
		else
			toAppend = this.formatPartialTotal(currenStep, totalStepCount);
		result.append(toAppend);
		result.append(this.endString);
		return result.toString();
	}
	/**
	 * Method that format the partial and the total count.
	 * @param currenStep The current step
	 * @param totalStepCount The number of total step
	 * @return A {@link String} representing the partial/total
	 */
	private String formatPartialTotal(int currenStep, int totalStepCount) {
		StringBuilder result = new StringBuilder();
	    if(this.showPartial)
	    	result.append(this.partialCountFormat.format(currenStep));
	    if(this.showPartial && this.showTotal)
	    	result.append("/");
	    if(this.showTotal)
	    	result.append(this.partialCountFormat.format(totalStepCount));
	    return result.toString();
    }
	/**
	 * Method that format the percentage.
	 * @param percentage The percentage value to format.
	 * @return A {@link String} representing the percentage 
	 */
	private String formatPercentage(double percentage) {
		if(!this.showPercentage)
			return "";
	    return this.percentageFormat.format(percentage);
    }
	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return super.toString();
	}
	/**
	 * Method that return the percentage format.
     * @return the percentageFormat
     */
    public DecimalFormat getPercentageFormat() {
    	return percentageFormat;
    }
	/**
	 * Method that return the partial count format.
     * @return the partialCountFormat
     */
    public DecimalFormat getPartialCountFormat() {
    	return partialCountFormat;
    }
	/**
	 * Method that return the {@link #showTotal} value.
	 * If this is value <code>true</code> this formatter print the total count.
     * @return the showTotal
     */
    public boolean isShowTotal() {
    	return showTotal;
    }
	/**
	 * Method that set the {@link #showTotal} value.
	 * If this value is <code>true</code> this formatter print the total count.
     * @param showTotal the showTotal to set
     */
    public void setShowTotal(boolean showTotal) {
    	this.showTotal = showTotal;
    }
	/**
	 * Method that return the {@link #showPartial} value.
	 * If this is value <code>true</code> this formatter print the partial count.
     * @return the showPartial
     */
    public boolean isShowPartial() {
    	return showPartial;
    }
	/**
	 * Method that set the {@link #showPartial} value.
	 * If this value is <code>true</code> this formatter print the partial count.
     * @param showPartial the showPartial to set
     */
    public void setShowPartial(boolean showPartial) {
    	this.showPartial = showPartial;
    }
	/**
	 * Method that return the {@link #showPercentage} value.
	 * If this value is <code>true</code> the formatter print the percentage value.
     * @return the showPercentage
     */
    public boolean isShowPercentage() {
    	return showPercentage;
    }
	/**
	 * Method that set the {@link #showPercentage} value.
	 * If this value is <code>true</code> the formatter print the show percentage value.
     * @param showPercentage the showPercentage to set
     */
    public void setShowPercentage(boolean showPercentage) {
    	this.showPercentage = showPercentage;
    }
	/**
	 * Method that return the {@link #firstPercentage} value.
	 * If this value is <code>true</code> the formatter print first the percentage value,
	 * and after the partial and total count.
     * @return the firstPercentage
     */
    public boolean isFirstPercentage() {
    	return firstPercentage;
    }
	/**
	 * Method that set the {@link #firstPercentage} value.
	 * If this value is <code>true</code> the formatter print first the percentage value,
	 * and after the partial and total count.
     * @param firstPercentage the firstPercentage to set
     */
    public void setFirstPercentage(boolean firstPercentage) {
    	this.firstPercentage = firstPercentage;
    }
	
}
